import json
import random
import re
from datetime import datetime

from flask import request, current_app, jsonify, make_response, session, abort, render_template, redirect, g

from info import constants, redis_store, db
from info.models import User
from info.utils.captcha.captcha import captcha
from info.utils.common import user_login_data
from info.utils.response_code import RET
from . import passport_blue


# 浏览器请求动态验证码
@passport_blue.route("/image_code")
def get_image_code():
    """
    1、获取浏览器发送的uuid
    2、生成图片验证码的name，文字，图片
    3、将uuid及图片验证码的文字存入redis数据库
    4、将图片返回给浏览器
    :return:
    """
    # 1、获取浏览器发送的uuid
    code_id = request.args.get("code_id", None)
    # 2、生成图片验证码的name，文字，图片
    name, text, image = captcha.generate_captcha()
    current_app.logger.debug("图片验证码内容是：%s" % text)
    # 3、将uuid及图片验证码的文字存入redis数据库,设置失效时间
    from info import redis_store
    try:
        redis_store.setex("ImageCode_" + code_id, constants.IMAGE_CODE_REDIS_EXPIRES, text)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DATAERR, errmsg="保存图片验证码失败")
    # 将图片返回给浏览器
    response = make_response(image)
    # 响应头中添加返回数据类型，方便浏览器解析
    response.headers["Contene-Type"] = "image/jpg"
    return response


from info.lib.yuntongxun.sms import CCP


# 短信验证码
@passport_blue.route("/sms_code", methods=["post"])
def send_sms():
    """
    1、接收UUID及图片验证码信息
    2、校验手机号是否正确
    3、从redis中取出UUID对应的信息
    4、判断其与发送过来的数据是否一致
    5、生成发送短信的内容，并发送
    6、将手机号与短信验证码存入redis，以便后期验证短信验证码时使用
    7、返回发送成功的响应
    :return:
    """
    # 1、接收参数并判断是否有值
    # param_dict = json.loads(request.date)
    # 获取数据json格式，将其转换为字典
    param_dict = request.json
    # 电话号码
    mobile = param_dict.get("mobile")
    # 输入的图片验证码
    image_code = param_dict.get("image_code")
    # uuid
    image_code_id = param_dict.get("image_code_id")
    # 判断是否全部有值
    if not all([mobile, image_code, image_code_id]):
        return jsonify(errno=RET.PARAMERR, errmsg="参数不全")
    # 2、校验手机号是否正确
    if not re.match(r"1[3578][0-9]{9}", mobile):
        return jsonify(errno=RET.DATAERR, errmsg="手机号不正确")

    user = None
    try:
        user = User.query.filter(User.mobile == mobile).all()
    except Exception as e:
        current_app.logger.error(e)
    if user:
        return jsonify(errno=RET.DATAEXIST, errmsg="该手机号已注册")
    # 3、从redis中取出UUID对应的信息
    try:
        real_image_code = redis_store.get("ImageCode_" + image_code_id)
        # print(image_code)
        # print(real_image_code)
    except Exception as e:
        current_app.logger.error(e)
        # 从数据库读取图片验证码失败
        return jsonify(errno=RET.DBERR, errmsg="获取图片验证码失败")
    # 如果未取到数据，可能验证码失效
    if not real_image_code:
        return jsonify(errno=RET.NODATA, errmsg="图片验证码已过期")
    # 4、判断其与发送过来的数据是否一致
    if real_image_code.upper() != image_code.upper():
        return jsonify(errno=RET.DATAERR, errmsg="图片验证码错误")
    # 5、生成发送短信的内容，并发送
    sms_code = "%06d" % random.randint(0, 999999)
    current_app.logger.debug("短信验证码内容是：%s" % sms_code)
    result = CCP().send_template_sms(mobile, [sms_code, constants.IMAGE_CODE_REDIS_EXPIRES // 60], 1)
    # print("-------")
    # print("111")
    # print("-------")
    # if result != 0:
    #     return jsonify(errno=RET.THIRDERR, errmsg="第三方软件错误")
    # 6、将手机号与短信验证码存入redis
    try:
        redis_store.set("SMS_" + mobile, sms_code, ex=constants.IMAGE_CODE_REDIS_EXPIRES)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg="存储短信验证码失败")
    # 7、返回发送成功的响应
    return jsonify(errno=RET.OK, errmsg="发送成功")


# 注册
@passport_blue.route("/register", methods=["post"])
def register():
    """
    1、获取参数
    2、校验参数
    3、根据获取得手机号从数据库取出短信验证码
    4、对比验证码是否一致
    5、初始化user对象，并将用户名、密码等存入数据库
    6、保存用户登录状态
    7、返回注册状态
    :return:
    """
    # 1、获取参数
    param_dict = request.json
    mobile = param_dict.get("mobile")
    smscode = param_dict.get("smscode")
    password = param_dict.get("password")
    # 2、校验参数
    if not all([mobile, smscode, password]):
        return jsonify(errno=RET.PARAMERR, errmsg="参数不足")
    # 3、根据获取得手机号从数据库取出短信验证码
    try:
        real_smscode = redis_store.get("SMS_" + mobile)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg="短信验证码读取失败")
    if not real_smscode:
        return jsonify(errno=RET.NODATA, errmsg="短信验证码失效")
    # 4、对比验证码是否一致
    if real_smscode != smscode:
        return jsonify(errno=RET.DATAERR, errmsg="验证码错误")
    # 从数据库中删除数据
    try:
        redis_store.delete("SMS_" + mobile)
    except Exception as e:
        current_app.logger.error(e)
    # 初始化user对象，并将用户名、密码等存入数据库
    user = User()
    user.nick_name = mobile
    user.mobile = mobile
    user.password = password
    try:
        db.session.add(user)
        db.session.commit()
    except Exception as e:
        db.session.rollback()
        current_app.logger.error(e)
        return jsonify(errno=RET.DATAERR, errmsg="数据添加错误")
    # 6、保存用户状态
    session["user_id"] = user.id
    session["nick_name"] = user.mobile
    session["mobile"] = user.mobile
    # 7、返回注册状态
    return jsonify(errno=RET.OK, errmsg="注册成功")


# 登录
@passport_blue.route("/login", methods=["post"])
def login():
    """
    1、获取数据，用户名，密码
    2、检验参数
    3、从数据库查找用户名
    4、检验密码
    5、登录状态保持
    6、返回登录状态
    :return:
    """
    # 1、获取参数
    param_dict = request.json
    mobile = param_dict.get("mobile")
    password = param_dict.get("password")

    # 2、校验参数
    if not all([mobile, password]):
        return jsonify(errno=RET.PARAMERR, errmsg="参数不足")

    # 3、从数据库查询用户
    try:
        user = User.query.filter(User.mobile == mobile).first()
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg="查询用户出错")

    if not user:
        return jsonify(errno=RET.NODATA, errmsg="用户未注册")

    # 4、利用函数检验密码，如
    if not user.check_passowrd(password):
        return jsonify(errno=RET.PWDERR, errmsg="密码错误")

    # 5、登录状态保持
    session["user_id"] = user.id
    session["nick_name"] = user.mobile
    session["mobile"] = user.mobile
    session["is_admin"] = user.is_admin

    # 记录最后一次登录时间
    last_login = datetime.now()
    # try:
    #     db.session.commit()
    # except Exception as e:
    #     current_app.logger.error(e)

    # 6、返回登录状态
    return jsonify(errno=RET.OK, errmsg="登录成功")


# 退出登录
@passport_blue.route("/logout", methods=["get", "post"])
def logout():
    """
    1、后端删除session中的值
    2、返回结果
    :return:
    """
    session.pop("user_id", None)
    session.pop("nick_name", None)
    session.pop("mobile", None)
    session.pop("is_admin", None)

    return jsonify(errno=RET.OK, errmsg="退出成功")
